package org.jackysoft.entity;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;

import org.apache.struts2.json.annotations.JSON;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Type;
import org.jackysoft.entity.AbstractEntity;
import org.jackysoft.entity.Department;
import org.jackysoft.entity.User;
import org.jackysoft.report.ReporterUtil;
import org.joda.time.DateTime;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate=true,dynamicInsert=true) 
public class MonthPlanning extends AbstractEntity {

    /**
	 * 
	 */
	private static final long serialVersionUID = 1428148732735274191L;
		
	
    private Department department;
    
	
    private DateTime createDate;
    
    private DateTime updateDate;
    
    private Double outputValue;      
    
    private Collection<MonthPlanningItem> dataItems = Lists.newArrayList();
    
    private User maker;
          	
    private MonthPlanningType planType;   
    
    private MonthPlanning  mother;
    
    private boolean draftable = false;
    
    
    

	public MonthPlanning(String id,Department department, DateTime createDate,User maker, MonthPlanningType planType) {
		super();
		this.id = id;
		this.department = department;
		this.createDate = createDate;		
		this.maker = maker;
		this.planType = planType;
	}

	public MonthPlanning() {
         super();
	}

	@ManyToOne
	@NotNull(message="请提供计划执行单位")
	public Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}
	
	@Type(type = "jodatime")
	public DateTime getCreateDate() {
		return createDate;
	}

	public void setCreateDate(DateTime createDate) {
		this.createDate = createDate;
	}

	@Type(type = "jodatime")
	public DateTime getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(DateTime updateDate) {
		this.updateDate = updateDate;
	}

	public Double getOutputValue() {
		return outputValue;
	}

	public void setOutputValue(Double outputValue) {
		this.outputValue = outputValue;
	}

	public void setDataItems(Collection<MonthPlanningItem> dataItems) {
		this.dataItems = dataItems;
	}

	@OneToMany(orphanRemoval=true)
	@org.hibernate.annotations.Cascade({CascadeType.ALL})	
	@JSON(serialize=false)
	public Collection<MonthPlanningItem> getDataItems() {
		return dataItems;
	}


	public void setMaker(User maker) {
		this.maker = maker;
	}

	@ManyToOne
	public User getMaker() {
		return maker;
	}

	public MonthPlanningType getPlanType() {
		return planType;
	}

	public void setPlanType(MonthPlanningType planType) {
		this.planType = planType;
	}

	@ManyToOne
	public MonthPlanning getMother() {
		return mother;
	}

	public void setMother(MonthPlanning mother) {
		this.mother = mother;
	}

	@Transient
	public Collection<MonthPlanningItem>  getProterozoic(){
		return typedItems(MonthPlanItemType.Proterozoic);
	}
	
	/**
	 * @return  所隶属产品=>生成计划项集合
	 * */
	@Transient@JSON(serialize=false)
	public Map<String,List<MonthPlanningItem>>  getGenerated(){		
		Map<String,List<MonthPlanningItem>> datas = Maps.newHashMap();
		List<MonthPlanningItem> merged = mergeitem(typedItems(MonthPlanItemType.Generated));
		for(MonthPlanningItem mp : merged){
			String hostCode = mp.getHost().getCode();
			List<MonthPlanningItem> mlist = datas.get(hostCode);
			if(mlist==null){
				mlist = Lists.newArrayList();
				datas.put(hostCode, mlist);
			}
			mlist.add(mp);
		}	
		
		return datas;
	}
	
	ReporterUtil reportUtil  = new ReporterUtil();
	
	@Transient@JSON(serialize=false)
	List<MonthPlanningItem> mergeitem(Collection<MonthPlanningItem> items){
		
		List<MonthPlanningItem> merged = Lists.newArrayList();
		for(MonthPlanningItem item : items){
			if(item==null)continue;
			MonthPlanningItem  itemFound =  reportUtil.find(merged, item);
		    if(itemFound==null){
		    	merged.add(item);
		    }else{
		        itemFound.setValue(itemFound.getValue()+item.getValue());
		        itemFound.getModifies().addAll(item.getModifies());
		    }
		}	
		
		return merged;
	}
	
	private Collection<MonthPlanningItem> typedItems(MonthPlanItemType itype){
		Collection<MonthPlanningItem> items = Lists.newArrayList();
		for(MonthPlanningItem mp : this.getDataItems()){
			if(mp==null) continue;
			if(mp.getItemType()==itype)
				items.add(mp);
		}
		
		return items;
		
	}

	public boolean isDraftable() {
		return draftable;
	}

	public void setDraftable(boolean draftable) {
		this.draftable = draftable;
	}
}